
#include "Graph.h"
#include <sstream>

int main()
{
	Graph MAP(10);

	MAP.addCity("Cairo");	//0
	MAP.addCity("Alex");	//1
	MAP.addCity("Matroh");	//2
	MAP.addCity("Giza");	//3
	MAP.addCity("Monofya");	//4
	MAP.addCity("Aswan");	//5
	MAP.addCity("Helwan");	//6
	MAP.addCity("Sywa");	//7


	MAP.addRoute(*MAP.getCity("Cairo"), *MAP.getCity("Alex"), 5);
	MAP.addRoute(*MAP.getCity("Cairo"), *MAP.getCity("Sywa"), 8);
	MAP.addRoute(*MAP.getCity("Cairo"), *MAP.getCity("Monofya"), 9);

	MAP.addRoute(*MAP.getCity("Alex"), *MAP.getCity("Sywa"), 4);
	MAP.addRoute(*MAP.getCity("Alex"), *MAP.getCity("Giza"), 12);
	MAP.addRoute(*MAP.getCity("Alex"), *MAP.getCity("Matroh"), 15);

	MAP.addRoute(*MAP.getCity("Matroh"), *MAP.getCity("Giza"), 3);
	MAP.addRoute(*MAP.getCity("Matroh"), *MAP.getCity("Sywa"), 7);
	MAP.addRoute(*MAP.getCity("Matroh"), *MAP.getCity("Aswan"), 1);
	MAP.addRoute(*MAP.getCity("Matroh"), *MAP.getCity("Helwan"), 11);

	MAP.addRoute(*MAP.getCity("Giza"), *MAP.getCity("Helwan"), 9);

	MAP.addRoute(*MAP.getCity("Monofya"), *MAP.getCity("Sywa"), 5);
	MAP.addRoute(*MAP.getCity("Monofya"), *MAP.getCity("Aswan"), 4);
	MAP.addRoute(*MAP.getCity("Monofya"), *MAP.getCity("Helwan"), 20);

	MAP.addRoute(*MAP.getCity("Aswan"), *MAP.getCity("Helwan"), 13);
	MAP.addRoute(*MAP.getCity("Aswan"), *MAP.getCity("Sywa"), 6);


	//MAP.addRoute(*MAP.getCity("Cairo"), *MAP.getCity("Matroh"), 26);
	//MAP.addRoute(*MAP.getCity("Cairo"), *MAP.getCity("Sywa"), 16);
	//MAP.addRoute(*MAP.getCity("Cairo"), *MAP.getCity("Monofya"), 38);
	//MAP.addRoute(*MAP.getCity("Cairo"), *MAP.getCity("Helwan"), 58);

	//MAP.addRoute(*MAP.getCity("Alex"), *MAP.getCity("Sywa"), 19);
	//MAP.addRoute(*MAP.getCity("Alex"), *MAP.getCity("Giza"), 29);
	//MAP.addRoute(*MAP.getCity("Alex"), *MAP.getCity("Matroh"), 36);
	//MAP.addRoute(*MAP.getCity("Alex"), *MAP.getCity("Aswan"), 32);


	//MAP.addRoute(*MAP.getCity("Matroh"), *MAP.getCity("Giza"), 17);
	//MAP.addRoute(*MAP.getCity("Matroh"), *MAP.getCity("Sywa"), 34);
	//MAP.addRoute(*MAP.getCity("Matroh"), *MAP.getCity("Helwan"), 40);

	//MAP.addRoute(*MAP.getCity("Giza"), *MAP.getCity("Helwan"), 52);

	//MAP.addRoute(*MAP.getCity("Monofya"), *MAP.getCity("Sywa"), 37);
	//MAP.addRoute(*MAP.getCity("Monofya"), *MAP.getCity("Aswan"), 35);
	//MAP.addRoute(*MAP.getCity("Monofya"), *MAP.getCity("Helwan"), 93);

	//MAP.addRoute(*MAP.getCity("Aswan"), *MAP.getCity("Sywa"), 28);






	while(true)
	{
		string line;
		string command;
		char *ch;
		cout << ">> ";

		getline( cin, line );
		stringstream(line) >> command;
		line.erase(0, command.size()+1);

		ch = (char*)command.c_str();

		switch (*ch)
		{
		case 'a':
			if(command == "addcity")
			{
				string city;
				stringstream(line) >> city;
				if(city.size() != 0 && city != " ")
					MAP.addCity(city);
				else
					cout << "Invalid City Name!" << endl;
			}

			else if(command == "addroute")
			{
				string city1;
				string city2;
				int distance;
				stringstream(line) >> city1;
				line.erase(0, city1.size()+1);
				stringstream(line) >> city2;
				line.erase(0, city2.size()+1);
				stringstream(line) >> distance;

				if(MAP.getCity(city1) != nullptr && MAP.getCity(city2) != nullptr && distance > 0)
					MAP.addRoute(*MAP.getCity(city1),*MAP.getCity(city2),distance);
				else if(MAP.getCity(city1) == nullptr)
					cout << city1 << " is not found"<< endl;
				else if(MAP.getCity(city2) == nullptr)
					cout << city2 << " is not found"<< endl;
				else if(distance <= 0)
					cout << "distance must be more than zero"<< endl;
			}
			break;
		case 's':
			if(command == "showmap")
				MAP.showGraph();

			else if(command == "showcities")
				MAP.showCities();

			else if(command == "spath")
			{
				string city1;
				string city2;
				Queue Qcities_;

				stringstream(line)>>city1;
				line.erase(0,city1.size()+1);
				stringstream(line)>>city2;
				line.erase(0,city2.size()+1);

				if(MAP.getCity(city1) != nullptr && MAP.getCity(city2) != nullptr)
				{
					int shortestPath;
					shortestPath = MAP.getShortestPath( *MAP.getCity(city1), *MAP.getCity(city2), Qcities_);
				
					Qcities_.reverse();
					int size = Qcities_.size();

					cout << "Shortest Path = " << shortestPath << endl;

					cout << Qcities_.peekHead().getName();

					for (int i = 0; i < size - 1; i++)
					{
						City city_temp = Qcities_.Dequeue();
						cout << " --(" << MAP.weight_Is(city_temp, Qcities_.peekHead()) << ")-- " << Qcities_.peekHead().getName();
					}
					cout << endl << endl;
				}
				else if(MAP.getCity(city1) == nullptr)
					cout << city1 << " is not found"<< endl;
				else if(MAP.getCity(city2) == nullptr)
					cout << city2 << " is not found"<< endl;

			}
			break;

		case 'b':
			if(command == "browse")
			{
				string city;
				stringstream(line) >> city;
				City* C = MAP.getCity(city);
				if(C != nullptr)
					MAP.showNeighbours(*C);
				else 
					cout << city << " is not found!" << endl;
			}

			break;

		case 'c':
			if (command == "cls")
				system("cls");

			else if (command == "clearmap")
				MAP.makeEmpty();
			break;

		case 'e':
			if (command == "end")
				return 0;
			break;

		case 'h':
			cout << endl << "\t\tcommand <param_1> <param_2> ... : description" << endl << endl << endl;
			
			cout << "  # addcity <city_name> : add new city called <city_name>"<< endl << endl;
			cout << "  # addroute <city1_name> <city2_name> <distance> : add new route between" << endl << "	<city1_name> and <city2_name> with distance <distance>" << endl << endl;
			cout << "  # browse <city_name> : prints all neighbours with all routes for <city_name>"<< endl << endl;
			cout << "  # clearmap : clears all cities and routes"<< endl << endl;
			cout << "  # showmap : show routes in map with it's weight and which cities connected by route"<< endl << endl;
			cout << "  # showcities : show all cities" << endl << endl;
			cout << "  # spath <city1_name> <city2_name> : calculate shortest path between" << endl << "	<city1_name> and <city2_name> and return the path and minimum cost of the graph" << endl << endl;
			cout << "  # mst <city> : get minimum spaining tree for a map stsrting from <city>" << endl << endl;
			cout << "  # nearest <city1_name> : get the nearst set from <city1_name>" << endl << endl;
			
			break;
		
		case 'm':
			if(command == "mst")
			{
				Graph *MST;
				string city;
				stringstream(line)>>city;
				if(MAP.getCity(city) != nullptr)
				{
					MST = MAP.getMST(*MAP.getCity(city));
					MST->showGraph();
				}

				else if(MAP.getCity(city) == nullptr)
					cout << city << " is not found"<< endl;

			}
			break;

		case 'n':
			if(command == "nearest")
			{
				City near;
				string city;
				stringstream(line)>>city;

				if(MAP.getCity(city) != nullptr)
				{
					near = *MAP.getNearestCity(*MAP.getCity(city));
					cout << city << " --(" << MAP.weight_Is(*MAP.getCity(city), near) <<")-- " << near.getName() << endl;
				}
				else if(MAP.getCity(city) == nullptr)
					cout << city << " is not found"<< endl;
			}
			break;
		default:
			cout << "command is not found!" << endl << endl;
			break;
		}
		
	}
	return 0;
}